package advanced进阶;

/**
 * 在synchronized没有优化之前，ReentrantLock优于synchronized，在优化之后，两者不相上下
 * synchronized是jvm提供的，ReentrantLock是jdk提供的
 * ReentrantLock把加锁的步骤超分成两个，加锁和解锁
 * 所以，在使用ReentrantLock时，要记得解锁
 * synchronized只支持非公平锁
 * ReentrantLock都支持
 *
 * synchronized实现是基于操作系统mutex锁实现
 * ReentrantLock是CAS+AQS（抽象队列实现器）实现
 * AQS维护一个队列
 *
 * 解决线程安全问题，通过枷锁的方式：
 * synchronized
 * ReentrantLock
 */

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * ReentrantLock使用步骤
 * 1.创建一个Lock实例ReentrantLock lock = new ReentrantLock();
 * 2.加锁lock.lock();
 * 3.释放锁lock。unlock();
 *
 * .await()//等待一个分组唤醒
 * .signal()//唤醒其他分组
 */
public class ReentrantLock类 {
/*
    public static void main(String[] args) {
        ReentrantLock lock = new ReentrantLock();
        try {
            lock.lock();
            System.out.println("执行");
        }finally {
            lock.unlock();
        }
    }

 */
static ReentrantLock lock = new ReentrantLock();
    //先创建三个唤醒的分组
    static Condition c1 = lock.newCondition();
    static Condition c2 = lock.newCondition();
    static Condition c3 = lock.newCondition();

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    lock.lock();
                    c1.await();//等待一个分组
                    c2.signal();//唤醒其他分组
                    System.out.println("A");
                }catch (Exception e){
                    e.printStackTrace();
                }finally {
                    lock.unlock();
                }
            }
        });

        Thread t2 = new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    lock.lock();
                    c2.await();//等待一个分组
                    c3.signal();//唤醒其他分组
                    System.out.println("B");
                }catch (Exception e){
                    e.printStackTrace();
                }finally {
                    lock.unlock();
                }
            }
        });

        Thread t3 = new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    lock.lock();
                    c3.await();//等待一个分组
                    c1.signal();//唤醒其他分组
                    System.out.println("C");
                }catch (Exception e){
                    e.printStackTrace();
                }finally {
                    lock.unlock();
                }
            }
        });

        t1.start();
        t2.start();
        t3.start();

        Thread.sleep(1000);//保证三个线程已经全部启动
        try {
            lock.lock();
            c1.signal();
        }finally {
            lock.unlock();
        }
    }
}